package com.fantuan.web;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.validator.EmailValidator;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fantuan.db.bean.LoginKey;
import com.fantuan.db.bean.User;

/**
 * 用户相关
 * 登录
 * 注册
 * 
 * @author Yoyo
 *
 */

@Service
@Controller
public class UserAction extends BaseAction{
	
	private static Log logger = LogFactory.getLog(UserAction.class);
	
	//首页，内部判断是否已登录
	@RequestMapping("/index.do")
	public Map<String, Object> processIndex(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();		
		isLogin( request );		
		return retMap;
	}	
	
	//登录相关方法
	/**
	 * 访问页面，中间无逻辑
	 * @param request
	 * @param response
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping("/login.do")
	public Map<String, Object> pageLogin(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();
		return retMap;
	}
	
	/**
	 * 处理登录信息的json,ajax用
	 * status=0 成功
	 * 其他 失败
	 * @param request
	 * @param response
	 * @param username
	 * @param password
	 * @param rememberflag
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping("/loginprocess.json")
	@ResponseBody
	public Map<String, Object> processLogin(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value="username",required=true) String username,
			@RequestParam(value="password",required=true) String password,
			@RequestParam(value="rememberflag",required=false) String rememberflag
			) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();
				
		logger.debug("用户登录处理");
		logger.debug("username=" + username);
		logger.debug("password=" + password);
		logger.debug("rememberflag=" + rememberflag);
		
		/**
		 * 邮箱不为空
		 */
		if( StringUtils.isBlank(username) )
		{
			retMap.put("status", -1);
			retMap.put("message", this.optionDAO.getOption("message.email.required").getOption_value());
			return retMap;
		}
		
		/**
		 * 内容校验
		 */
		EmailValidator emailValidator = EmailValidator.getInstance();
		if( !emailValidator.isValid(username) )
		{
			retMap.put("status", -1);
			retMap.put("message", this.optionDAO.getOption("message.email.format").getOption_value());
			return retMap;
		}
		
		/**
		 * 密码不为空
		 */
		if( StringUtils.isBlank(password) )
		{
			retMap.put("status", -2);
			retMap.put("message", this.optionDAO.getOption("message.password.required").getOption_value());
			return retMap;
		}		
		
		//判断登录数据正确性
		User loginuser = this.ftService.login(username, password);		
		
		if( loginuser == null )//登录失败
		{
			retMap.put("status", -3);
			retMap.put("message", this.optionDAO.getOption("message.login.error").getOption_value());
			return retMap;
		}
		else//登录成功
		{
			retMap.put("status", 0);
			//用户信息保存在session
			saveLoginUserToSession(request, loginuser);
			
			//免登录标记，记录在cookie中
			if( StringUtils.isNotBlank( rememberflag ) )//cookie记录用户信息
			{
				this.saveLoginUserToCookie( response, loginuser );
			}
			else
			{
				this.removeLoginUserFromCookie( response );
			}
			
			//更新数据库中登录时间和次数
			loginuser.setdLoginDate(new Date());//最后登陆时间
			loginuser.setnLoginTimes(loginuser.getnLoginTimes()==null?1:loginuser.getnLoginTimes()+1);
			this.userDAO.updateUser(loginuser);
		}
		
		return retMap;
	}	
	
	/**
	 * 保存用户登录信息到session
	 * @param request
	 */
	private void saveLoginUserToSession( HttpServletRequest request, User loginuser )
	{
		request.getSession().setAttribute("login", loginuser);
	}
	
	/**
	 * 从session中获取用户信息
	 * @param request
	 * @return
	 */
	private User getLoginUserFromSession( HttpServletRequest request )
	{
		return (User)request.getSession().getAttribute("login");
	}
	
	//更改密码相关方法，上面是登录相关
	/**
	 * 访问页面，忘记密码页面，输入邮箱后进入更改密码逻辑
	 * @param request
	 * @param response
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping("/findpwd.do")
	public Map<String, Object> pageFindpwd(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();
		return retMap;
	}
	
	/**
	 * 更新密码页面
	 * 进入方式1：用户登录后修改
	 * 进入方式2：找回密码操作，邮件链接进入
	 * @param request
	 * @param response
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping("/updatepwd.do")
	public Map<String, Object> pageUpdatepwd(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		//方式2：默认登录
		String mkey = request.getParameter("mkey");
		if( StringUtils.isNotBlank(mkey) )
		{
			//有mkey参数则先登出系统
			this.processLogout(request, response);
			//数据库中获取对应的邮箱
			LoginKey loginKey = loginKeyDAO.getLoginKey(mkey);
			if( loginKey != null )
			{
				//20分钟内
				if( System.currentTimeMillis()-loginKey.getDvalidTime().getTime() < DateUtils.MILLIS_PER_MINUTE*20 )
				{
					User user = this.userDAO.getUser(loginKey.getUserId());
					this.saveLoginUserToSession(request, user);
				}
				
				this.loginKeyDAO.removeLoginKey(loginKey.getId());
			}
		}
		
		Map<String, Object> retMap = new HashMap<String, Object>();
		//正常流程，如果已经登录则可以修改
		if( !this.isLogin(request) )
		{
			retMap.put("status", -21);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
		}
		else
		{
			retMap.put("status", 0);
		}		
		
		return retMap;
	}
	
	@RequestMapping("/findpwdprocess.json")
	@ResponseBody
	public Map<String, Object> processFindpwd(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value="email",required=false) String email
			) throws SQLException
	{
		logger.debug("找回密码处理");
		
		Map<String, Object> retMap = new HashMap<String, Object>();
				
		/**
		 * 1.必须输入校验
		 */
		EmailValidator emailValidator = EmailValidator.getInstance();
		if( !emailValidator.isValid(email) )
		{
			retMap.put("status", -1);
			retMap.put("message", this.optionDAO.getOption("message.email.format").getOption_value());
			return retMap;
		}		
		
		/**
		 * 2.数据校验
		 */
		User user = this.userDAO.getUserByEmail(email);
		//logger.debug("user=" + user);
		if( user == null )
		{
			retMap.put("status", -11);
			retMap.put("message", this.optionDAO.getOption("message.email.noregister").getOption_value());
			return retMap;
		}
		
		//发提醒邮件，等待添加
		LoginKey loginKey = getNewLoginKey(user.getnID());
		logger.debug("skey=" + loginKey.getSkey());		
		
		String urlheader = StringUtils.substringBeforeLast( request.getRequestURL().toString(), "/");
		String url = urlheader + "updatepwd.do?mkey=" + loginKey.getSkey();//邮件中的链接
		
		retMap.put("status", 0);
		retMap.put("message", this.optionDAO.getOption("message.email.updatepwd.send.success").getOption_value());
		retMap.put("url", url);//邮件用
		retMap.put("user", user);//邮件用	
		
		//邮件
		String subject = "饭团网-找回密码";
		String vmfile = "mail/test.vm";
		String[] mailTo = new String[]{email};
		this.mailService.sendEmail(retMap, subject, vmfile, mailTo, null);
				
		return retMap;
	}
	
	//注册逻辑相关，上面是修改密码部分	
	@RequestMapping("/register.do")
	public Map<String, Object> pageRegister(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();
		return retMap;
	}
	
	@RequestMapping("/registerprocess.json")
	@ResponseBody
	public Map<String, Object> processRegister(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value="email",required=false) String email,
			@RequestParam(value="username",required=false) String username,
			@RequestParam(value="password1",required=false) String password1,
			@RequestParam(value="password2",required=false) String password2
			) throws SQLException
	{
		logger.debug("用户注册处理");
		
		Map<String, Object> retMap = new HashMap<String, Object>();
				
		/**
		 * 1.必须输入校验
		 */
		EmailValidator emailValidator = EmailValidator.getInstance();
		if( !emailValidator.isValid(email) )
		{
			retMap.put("status", -1);
			retMap.put("message", this.optionDAO.getOption("message.email.format").getOption_value());
			return retMap;
		}
		
		if( StringUtils.isBlank(username) )
		{
			retMap.put("status", -2);
			retMap.put("message", this.optionDAO.getOption("message.username.required").getOption_value());
			return retMap;
		}
		
		if( !StringUtils.equals(password1, password2) || StringUtils.isBlank(password1) )
		{
			retMap.put("status", -3);
			retMap.put("message", this.optionDAO.getOption("message.password.two.equal").getOption_value());
			return retMap;
		}
		
		/**
		 * 2.数据校验
		 */
		User user = this.userDAO.getUserByEmail(email);
		logger.debug("user=" + user);
		if( user != null )
		{
			retMap.put("status", -11);
			retMap.put("message", this.optionDAO.getOption("message.email.hasregister").getOption_value());
			return retMap;
		}
		
		//新增用户
		User registerUser = new User();
		registerUser.setsEMail(email);
		registerUser.setnState(2);//未激活状态
		registerUser.setsNickName(username);
		registerUser.setsPassword(password1);
		long userid = this.userDAO.addUser(registerUser);
		
		//发提醒邮件，等待激活
		LoginKey loginKey = getNewLoginKey((int)userid);
		logger.debug("skey=" + loginKey.getSkey());
		
		String urlheader = StringUtils.substringBeforeLast( request.getRequestURL().toString(), "/");
		String url = urlheader + "activeemailresult.do?mkey=" + loginKey.getSkey();
		retMap.put("status", 0);
		retMap.put("url", url);
		retMap.put("message", this.optionDAO.getOption("message.register.success").getOption_value());
		retMap.put("user", registerUser);
		
		//邮件
		String subject = "饭团网-注册用户激活";
		String vmfile = "mail/test.vm";
		String[] mailTo = new String[]{email};
		this.mailService.sendEmail(retMap, subject, vmfile, mailTo, null);
				
		return retMap;
	}
	
	
	//激活邮箱
	@RequestMapping("/activeemailresult.do")
	public Map<String, Object> activeemailresult(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		//必须是邮件触发，所以先登出
		this.processLogout(request, response);
		
		//方式2：默认登录
		String mkey = request.getParameter("mkey");
		if( StringUtils.isNotBlank(mkey) )
		{
			//数据库中获取对应的邮箱
			LoginKey loginKey = loginKeyDAO.getLoginKey(mkey);
			if( loginKey != null )
			{
				//20分钟内
				if( System.currentTimeMillis()-loginKey.getDvalidTime().getTime() < DateUtils.MILLIS_PER_MINUTE*20 )
				{
					User user = this.userDAO.getUser(loginKey.getUserId());
					this.saveLoginUserToSession(request, user);
				}
				
				//删除这一条
				loginKeyDAO.removeLoginKey(loginKey.getId());
			}
		}
		
		Map<String, Object> retMap = new HashMap<String, Object>();
		//正常流程，如果已经登录则可以修改
		if( !this.isLogin(request) )
		{
			retMap.put("status", -21);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
		}
		else
		{
			User loginuser = this.getLoginUserFromSession(request);
			loginuser.setnState(0);//激活状态
			loginuser.setdLoginDate(new Date());//最后登陆时间
			loginuser.setnLoginTimes(loginuser.getnLoginTimes()==null?1:loginuser.getnLoginTimes()+1);
			this.userDAO.updateUser(loginuser);
			
			retMap.put("status", 0);
			retMap.put("message", this.optionDAO.getOption("message.email.active.success").getOption_value());
		}
		
		return retMap;
	}
	
	
	
	
	@RequestMapping("/updateemailresult.do")
	public Map<String, Object> updateemailresult(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		//必须是邮件触发，所以先登出
		this.processLogout(request, response);
		
		//方式2：默认登录
		String mkey = request.getParameter("mkey");
		if( StringUtils.isNotBlank(mkey) )
		{
			//数据库中获取对应的邮箱
			LoginKey loginKey = loginKeyDAO.getLoginKey(mkey);
			if( loginKey != null )
			{
				//20分钟内
				if( System.currentTimeMillis()-loginKey.getDvalidTime().getTime() < DateUtils.MILLIS_PER_MINUTE*20 )
				{
					User user = this.userDAO.getUser(loginKey.getUserId());
					this.saveLoginUserToSession(request, user);
				}
				
				//删除这一条
				loginKeyDAO.removeLoginKey(loginKey.getId());
			}
		}
		
		Map<String, Object> retMap = new HashMap<String, Object>();
		//正常流程，如果已经登录则可以修改
		if( !this.isLogin(request) )
		{
			retMap.put("status", -21);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
		}
		else
		{
			String email = request.getParameter("newemail");
			//更新数据库
			User registerUser = this.getLoginUserFromSession(request);
			registerUser.setdLoginDate(new Date());//最后登陆时间
			registerUser.setnLoginTimes(registerUser.getnLoginTimes()==null?1:registerUser.getnLoginTimes()+1);
			registerUser.setsEMail(email);
			this.userDAO.updateUser(registerUser);
			
			retMap.put("status", 0);
			retMap.put("message", this.optionDAO.getOption("message.email.update.success").getOption_value());
		}
		
		return retMap;
	}
	
	/**
	 * 更新邮箱
	 * @param request
	 * @param response
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping("/updateemail.do")
	public Map<String, Object> pageUpdateemail(HttpServletRequest request,
			HttpServletResponse response) throws SQLException
	{
		Map<String, Object> retMap = new HashMap<String, Object>();
		//正常流程，如果已经登录则可以修改，必须登录状态
		if( !this.isLogin(request) )
		{
			retMap.put("status", -21);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
		}
		else
		{
			retMap.put("status", 0);
		}		
		
		return retMap;
	}
	
	@RequestMapping("/updateemailprocess.json")
	@ResponseBody
	public Map<String, Object> processUpdateemail(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value="email",required=false) String email
			) throws SQLException
	{
		logger.debug("更新邮箱处理");
		
		Map<String, Object> retMap = new HashMap<String, Object>();
				
		//新增用户
		User registerUser = this.getLoginUserFromSession(request);
		if( registerUser == null )
		{
			retMap.put("status", -4);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
			return retMap;
		}
		
		if( StringUtils.equals(registerUser.getsEMail(),email) )
		{
			retMap.put("status", -5);
			retMap.put("message", this.optionDAO.getOption("message.email.nochange").getOption_value());
			return retMap;
		}
		
		EmailValidator emailValidator = EmailValidator.getInstance();
		if( !emailValidator.isValid(email) )
		{
			retMap.put("status", -1);
			retMap.put("message", this.optionDAO.getOption("message.email.format").getOption_value());
			return retMap;
		}
		
		//邮箱应该没有被注册过
		User user = this.userDAO.getUserByEmail(email);
		if( user != null )
		{
			retMap.put("status", -2);
			retMap.put("message", this.optionDAO.getOption("message.email.hasregister").getOption_value());
			return retMap;
		}		
		
		//发提醒邮件，等待添加
		LoginKey loginKey = getNewLoginKey(registerUser.getnID());
		logger.debug("skey=" + loginKey.getSkey() + ",newemail=" + email);
		
		String urlheader = StringUtils.substringBeforeLast( request.getRequestURL().toString(), "/");
		String url = urlheader + "/updateemailresult.do?mkey=" + loginKey.getSkey() + "&newemail=" + email;
				
		retMap.put("status", 0);
		retMap.put("message", this.optionDAO.getOption("message.email.update.mail").getOption_value());
		retMap.put("url", url);
		retMap.put("user", registerUser);
		
		//邮件
		String subject = "饭团网-更新邮箱";
		String vmfile = "mail/test.vm";
		String[] mailTo = new String[]{email};
		this.mailService.sendEmail(retMap, subject, vmfile, mailTo, null);
				
				
		return retMap;
	}
	
	
	@RequestMapping("/updatepwdprocess.json")
	@ResponseBody
	public Map<String, Object> processUpdatepwd(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value="password1",required=false) String password1,
			@RequestParam(value="password2",required=false) String password2
			) throws SQLException
	{
		logger.debug("更新密码处理");
		
		Map<String, Object> retMap = new HashMap<String, Object>();
		
		if( !StringUtils.equals(password1, password2) || StringUtils.isBlank(password1) )
		{
			retMap.put("status", -3);
			retMap.put("message", this.optionDAO.getOption("message.password.two.equal").getOption_value());
			return retMap;
		}
		
		//新增用户
		User registerUser = this.getLoginUserFromSession(request);
		if( registerUser == null )
		{
			retMap.put("status", -4);
			retMap.put("message", this.optionDAO.getOption("message.login.before").getOption_value());
			return retMap;
		}
		
		//更新数据库
		registerUser.setdLoginDate(new Date());//最后登陆时间
		registerUser.setnLoginTimes(registerUser.getnLoginTimes()==null?1:registerUser.getnLoginTimes()+1);
		registerUser.setsPassword(password1);
		this.userDAO.updateUser(registerUser);
				
		retMap.put("status", 0);
		retMap.put("message", this.optionDAO.getOption("message.password.update.success").getOption_value());
		
		return retMap;
	}
	
	
	
	
	
	

	
	

	
	/**
	 * 从session中清除用户登录信息
	 * @param request
	 */
	private void removeLoginUserFromSession( HttpServletRequest request )
	{
		request.getSession().removeAttribute("login");
	}	
	
	/**
	 * 从cookie清除用户信息
	 * @param request
	 * @return
	 */
	private void removeLoginUserFromCookie(HttpServletResponse response)
	{
		//清空cookie
		String cookiename = "loginusername";
		String cookievalue = "";		
		Cookie cookie = new Cookie(cookiename, cookievalue);
		cookie.setPath("/");
		cookie.setMaxAge((int) (DateUtils.MILLIS_PER_DAY * 365 / DateUtils.MILLIS_PER_SECOND));
		response.addCookie(cookie);		
	}	
	
	/**
	 * 保存用户信息到cookie
	 * @param response
	 * @param loginuser
	 */
	private void saveLoginUserToCookie(HttpServletResponse response, User loginuser)
	{
		//清空cookie
		String cookiename = "loginusername";
		String cookievalue = loginuser.getsEMail();		
		Cookie cookie = new Cookie(cookiename, cookievalue);
		cookie.setPath("/");
		cookie.setMaxAge((int) (DateUtils.MILLIS_PER_DAY * 365 / DateUtils.MILLIS_PER_SECOND));
		response.addCookie(cookie);	
	}
	
	
	/**
	 * 从cookie中获取登录用户信息
	 * @param request
	 * @return
	 * @throws SQLException
	 */
	private User getLoginUserFromCookie(HttpServletRequest request)
			throws SQLException {
		String cookiename = "loginusername";
		if (ArrayUtils.isNotEmpty(request.getCookies()))
		{
			for (Cookie cookie : request.getCookies()) {
				// cookie中寻找
				if (StringUtils.equals(cookie.getName(), cookiename) && StringUtils.isNotBlank(cookie
							.getValue())) {
					User loginuser = this.userDAO.getUserByEmail(cookie
							.getValue());

					if (loginuser != null) {
						saveLoginUserToSession(request, loginuser);
						return loginuser;
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * 判断用户是否已经登录，cookie中的算登录
	 * @param request
	 * @return
	 * @throws SQLException
	 */
	public boolean isLogin( HttpServletRequest request ) throws SQLException
	{
		User loginuser = getLoginUserFromSession(request);
		if( loginuser != null )
		{
			return true;
		}
		
		loginuser = getLoginUserFromCookie(request);
		if( loginuser != null )
		{
			return true;
		}
		
		return false;
	}
	
	@RequestMapping("/logout.do")	
	public Map<String, Object> pageLogout(HttpServletRequest request,
			HttpServletResponse response)
	{		
		Map<String, Object> retMap = new HashMap<String, Object>();
		return retMap;
	}	
	
	@RequestMapping("/logoutprocess.do")	
	public String processLogout(HttpServletRequest request,
			HttpServletResponse response)
	{		
		//清空session
		removeLoginUserFromSession( request );
		
		//清空cookie
		removeLoginUserFromCookie( response );
		
		logger.debug("用户登出操作完成");
		
		return "redirect:" + "login.do";
	}
	
	
	
	private LoginKey getNewLoginKey( int userid ) throws SQLException
	{
		String skey = RandomStringUtils.randomAlphanumeric(25);
		LoginKey loginKey = new LoginKey();
		loginKey.setDvalidTime(new Date());
		loginKey.setNstate(0);
		loginKey.setNtype(0);
		loginKey.setUserId(userid);
		loginKey.setSkey(skey);
		loginKey.setId( (int)this.loginKeyDAO.addLoginKey(loginKey) );
		
		return loginKey;
	}
	
	
}